package Acelerometro;

/*
 * Representa el acelerómetro y la manera en la que el sensor obtiene la información de las
 * coordenadas.
 */

import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.sensor.Data;
import javax.microedition.sensor.DataListener;
import javax.microedition.sensor.SensorConnection;
import javax.microedition.sensor.SensorInfo;
import javax.microedition.sensor.SensorManager;

/**
 * Abre un canal al acelerometro, y busca que tipo de valor puede dar el sensor,
 * enteros o double
 * Regresa los valores de X,Y,Z en enteros
 *
 *Desarrolladores:
 *Equipo: The Dream Team
 *José Francisco Ruiz Martínez 		A01166298
 *José Héctor Bermúdez Robles		A01161142
 *Arturo Ramírez Morales	        A01165819
 *@version 1.0  Noviembre 2010
 */
public class Acelerometro implements DataListener, Runnable { // DataListener registra cuando ocurren cambios en los datos

    private int xSensor, ySensor, zSensor;            // Direcciones del sensor
    private static SensorConnection sensor = null;
    private SensorInfo infos[];                 // InformaciÃ³n de los sensores
    private static boolean isStopped = false;   // Indica si estÃ¡ corriendo el thread o no
    private static boolean sensor_found = false;// Indica si se encontrÃ³ el sensor adecudado
    private static final int BUFFER_SIZE = 3;   // Buffer que guarda la informaciÃ³n
    private Thread thread = null;               // Thread para inicializar el sensor

    /**
     * Inicializa o abre el sensor y actualiza el DataListener
     */
    private synchronized void initSensor() {
        sensor = openSensor();
        if (sensor == null) {
            // imprimir que no es compatible
            return;
        }
        try {
            sensor.setDataListener(this, BUFFER_SIZE);
            while (!isStopped) {
                try {
                    wait();
                } catch (InterruptedException ie) {
                }
            }
            sensor.removeDataListener();
        } catch (IllegalMonitorStateException imse) {

        } catch (IllegalArgumentException iae) {

        }
        try {
            sensor.close();
        } catch (IOException ioe) {

        }
        if (isStopped) {
            sensor = null;
        }
    }

    /**
     * Busca los sensores para el acelerÃ³metro y si los encuentra regresa un
     * SensorConnection en el que se establece la conexiÃ³n.
     * El sesor se utiliza con enteros.
     * @return SensorConnection, el cual se abre de acuerdo al sensor
     */
    private SensorConnection openSensor() {
        infos = SensorManager.findSensors("acceleration", null);
        if (infos.length == 0) {
            return null;
        }
        int datatypes[] = new int[infos.length];
        int i = 0;
        String sensor_url = "";

      //  System.out.println("Searching TYPE_INT sensor...");
        while (!sensor_found) {
            datatypes[i] = infos[i].getChannelInfos()[0].getDataType();
            if (datatypes[i] == 2) { //ChannelType.TYPE_INT = 2
                sensor_url = infos[i].getUrl();
             //   System.out.println("Sensor: " + sensor_url + ": TYPE_INT found.");
                sensor_found = true;
            } else {
                i++;
            }
        }

        System.out.println("Sensor: " + sensor_url);
        try {
            return (SensorConnection) Connector.open(sensor_url);
        } catch (IOException ioe) {

            return null;
        }
    }

    /**
     * NotificaciÃ³n de la informaciÃ³n recibida pro el sensor.
     * @param sensor - SensorConnection, donde se origina la toma de informaciÃ³n
     * @param data - la que se recibe del sensro
     * @param isDataLost - es verdadera si se pierde informaciÃ³n
     */
    public void dataReceived(SensorConnection sensor, Data[] data, boolean isDataLost) {

        int[] directions = getIntegerDirections(data);
        xSensor = directions[0];
        ySensor = directions[1];
        zSensor = directions[2];


    }

    /**
     * Obtiene las coordenadas en el eje "x", "y" y "z" del acelerÃ³metro.
     * Se calcula un valor promedio de los datos obtenidos del buffer.
     * @param data, informaciÃ³n del sensor
     * @return directions,  arreglo con los valores del sensor
     */
    private static int[] getIntegerDirections(Data[] data) {
        int[][] intValues = new int[3][BUFFER_SIZE];
        int[] directions = new int[3];
        for (int i = 0; i < 3; i++) {
            intValues[i] = data[i].getIntValues();
            int temp = 0;
            for (int j = 0; j < BUFFER_SIZE; j++) {
                temp = temp +(int)intValues[i][j];
            }
            directions[i] = temp / BUFFER_SIZE;
        }
        return directions;
    }

    private synchronized void setStopped(boolean stopped) { // lo forza a detenerse
        isStopped = stopped;
        notify();
        if (thread != null) {
            thread = null;
        }
    }
/**
 * Acitva el sensor, es sicronizado porque utiliza recursos compartidos
 */
    public synchronized void start() { //activa el sensor
        setStopped(false);
        if (thread == null) {
            thread = new Thread(this);
        }
        thread.start();
    }

 /**
 * Desactiva el sensor, es sicronizado porque utiliza recursos compartidos
 */
    public synchronized void stop() { // detiene el sensor
        sensor.removeDataListener();
        try {
            sensor.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        setStopped(true);
        thread = null;
    }

    /**
     * Inicializa el sensor
     */
    public void run() { //inicializa el sensor
        initSensor();
    }

    /**
     * Obtiene la informaciÃ³n del sensor en "x"
     * @return la coordenada en "x" del acelerÃ³metro
     */
    public int getxSensor() {
        return xSensor;
    }

 /**
     * Obtiene la informaciÃ³n del sensor en "y"
     * @return la coordenada en "y" del acelerÃ³metro
     */
    public int getySensor() {
        return ySensor;
    }

 /**
     * Obtiene la informaciÃ³n del sensor en "z"
     * @return la coordenada en "z" del acelerÃ³metro
     */
    public int getzSensor() {
        return zSensor;
    }


}

